#include "my.h"

typedef struct
{
	int type;  //请求的类型
	char username[50];
	char passwd[50];
	
	char filename[50];	//保存文件名
	char filedata[1000];	//保存文件内容
	int len;
}data_t;


int flag = 0;//0代表当前显示菜单1, 3代表显示菜单界面二

//给服务器发送的注册请求函数
void registerRequest(int sockfd)
{
	//1.定义一个结构体变量装上　请求类型 用户名 密码
	data_t s = { 0 };
	s.type = 1;//1 代表注册请求
	printf("请您输入要注册的用户名:\n");
	scanf("%s%s",s.username, s.passwd);
	//2.将请求　用户名和密码发送给服务器
	send(sockfd, &s, sizeof(s), 0);
	//3.阻塞接收服务器的应答
	recv(sockfd, &s, sizeof(s), 0);
	if(s.type == 0)
		printf("恭喜%s,注册成功!!\n",s.username);
	else if(s.type == -1)
		printf("非常抱歉%s, 用户名已经被注册!!!\n",s.username);
	
}


void loginRequest(int sockfd, data_t *userinfo)
{
    data_t s = {0};
    s.type = 2;
    
    printf("请您输入要登录的用户名:\n");
    scanf("%s", s.username);
    printf("请您输入密码:\n");
    scanf("%s", s.passwd);
    
    send(sockfd, &s, sizeof(s), 0);
    recv(sockfd, &s, sizeof(s), 0);  
    *userinfo = s;  
    
    if(s.type == -1)
        printf("登录的用户名不存在：\n");
    else if(s.type == -2)
        printf("登录的密码错误\n");
    else if(s.type == 0)
    {
        flag = 3;
        printf("登录成功！欢迎 %s\n", s.username);
    }
}


void fileTransfer(int sockfd,data_t *userinfo)
{
    char pathName[100]; // 用来保存上传文件的绝对路径
    char dirName[50];   // 用来保存你要上传的文件所在的目录的绝对路径
    
    // 1.定义结构体变量s，装东西
    data_t s = *userinfo;
    s.type = 4; // 4代表上传文件请求
 
    
    printf("请您输入要上传的文件所在目录的绝对路径:\n");
    scanf("%s", dirName); 
    
    printf("请输入要上传文件的名字\n");
    scanf("%s", s.filename); 
    
    // /home/Linux/Public/haha.c
    sprintf(pathName, "%s/%s", dirName, s.filename); // 添加了缺少的斜杠
    
    // 2.用系统IO打开文件
    int fd = open(pathName, O_RDONLY);
    if(fd == -1)
    {
        perror("open failed");
        return;
    }
    
    // 3.循环读取文件中的内容，读取一次，发送一次给服务器
    while((s.len = read(fd, s.filedata, sizeof(s.filedata))) > 0) // 修正为s.len
    {
        send(sockfd, &s, sizeof(s), 0);
        usleep(10*1000); // 延时10ms
    }
    
    // 4.关闭文件
    close(fd);
    
    printf("文件 %s 上传完成!\n", s.filename);
}
void getListRequest(int sockfd, data_t *userinfo)
{
    data_t s = *userinfo;  // 保存用户信息
    s.type = 3;             // 设置请求类型
    
    // 发送请求
    if(send(sockfd, &s, sizeof(s), 0) <= 0)
    {
        printf("发送列表请求失败\n");
        return;
    }
    
    printf("文件列表:\n");
    printf("==========\n");
    
    // 使用不同的变量接收响应
    data_t response;
    int file_count = 0;
    
    while(1)
    {
        int ret = recv(sockfd, &response, sizeof(response), 0);
        if(ret <= 0)
        {
            printf("接收文件列表失败\n");
            break;
        }
        
        if(response.type == 0)  // 列表结束标记
        {
            printf("==========\n");
            printf("共 %d 个文件\n", file_count);
            break;
        }
        else if(response.type == 3)  
        {
            file_count++;
            printf("%d. %s\n", file_count, response.filename);
        }
    }
}

//菜单界面
void showMenu()
{
		if(flag == 0)
		{
			printf("\n****************************************\n");
			printf("*            名  你  做  主           *");
			printf("\n****************************************\n");
			printf("\n*      1.注册    2.登录    3.退出      *\n");
			printf("\n****************************************\n");
			printf("\n请 输 入 您 的 选 择:\n\n");
		}
		else if(flag == 3)
		{
			printf("\n/////////////////////////////////////////////////////");
			printf("\n*****************************************************\n");
			printf("*           欢　迎　使　用　小  度  网   盘  　    *");
			printf("\n*****************************************************\n");
			printf("\n* 1.列表  2.上传文件  3.下载文件 4.历史记录  5.退出*\n"); //4 5 6 7 8
			printf("\n*****************************************************\n");
			printf("/////////////////////////////////////////////////////\n");
			printf("\n请 输 入 您 的 选 择:\n\n");
		}
}


getDowmFile(int sockfd,data_t *userinfo)
{
	char dirName[100] = { 0 };//用来保存下载文件保存到的位置
	char pathName[100];//保存绝对路径
	data_t s = *userinfo;
	//1.输入要下载文件的名字
	s.type = 5;//5代表下载请求

	printf("请输入要下载文件的名字:\n");
	scanf("%s",s.filename);
	printf("请输入要将下载文件保存到的位置:\n");
	scanf("%s",dirName);
	sprintf(pathName,"%s/%s",dirName, s.filename);
	//2.发送给服务器
	send(sockfd, &s, sizeof(s), 0);
	//3.接收服务器的应答，下载的文件是否存在
	recv(sockfd, &s, sizeof(s), 0);
	if(s.len == -1)//说明下载的文件不存在
		printf("下载的%s不存在!!\n",s.filename);
	else
	{
		printf("下载的%s存在!!\n",s.filename);
		int fd = open(pathName, O_WRONLY|O_CREAT|O_TRUNC,0666);
		if(fd == -1)
		{
			perror("open failed");
			exit(-1);
		}
		//循环接收，收到一次，写入文件一次
		while(1)
		{
			recv(sockfd, &s, sizeof(s), 0);
			if(s.len == -2)//全部接收完毕
			{
				printf("%s下载完毕!!\n",s.filename);
				close(fd);
				break;
			}
			write(fd, s.filedata, s.len);
		}
	}
	

}
void getHiistoryInfoRequest(int sockfd,data_t *userinfo)
{ 
	data_t s = *userinfo;
	s.type = 6;
	while(1)
	{
		recv(sockfd,&s,sizeof(s),0);
		if(s.type == -1)
		{
			break;

		}
		printf("%s",s.filedata);
	}
}

int main(int argc, const char *argv[])
{
	int choose;
	//1.创建流式套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		perror("socket failed");
		exit(-1);
	}
	//2.连接服务器
	struct sockaddr_in toaddr = { 0 };
	toaddr.sin_family = AF_INET;
	toaddr.sin_port = htons(6666);
	toaddr.sin_addr.s_addr = inet_addr("192.168.0.11");
	connect(sockfd, (struct sockaddr*)&toaddr, sizeof(toaddr));



	data_t s = {0};
   	
	while(1)
	{
		showMenu();//显示菜单
		scanf("%d",&choose);
		if(flag == 0 && choose > 3)
		{
			printf("输入的选择不合理,请重新输入选择!!!\n");
			continue;
		}
		switch(choose+flag)
		{
		case 1://注册请求
			registerRequest(sockfd);//给服务器发送一个注册请求
			break;
		case 2://登录请求
			loginRequest(sockfd,&s);//给服务器发送一个登录请求
			break;
		case 3://退出客户端
			printf("欢迎下次使用!! 3s后结束程序!!\n");
			sleep(3);
			exit(0);
		case 4://获取列表请求
			getListRequest(sockfd,&s);
			break;
		case 5: //上传文件
			fileTransfer(sockfd,&s);
		case 6://下载请求
			getDowmFile(sockfd,&s);
			break;
		case 7://获取历史
			getHiistoryInfoRequest(sockfd,&s);

			break;
		}
	}
	return 0;
}
